package wowraidmanager.client.auction.data;

import java.util.ArrayList;
import java.util.Date;

import wowraidmanager.client.BaseComposite;
import wowraidmanager.client.auction.data.calculate.CalculateData;
import wowraidmanager.client.auction.data.canvas.DrawDistributionCanvas;
import wowraidmanager.client.auction.data.canvas.DrawExampleCanvas;
import wowraidmanager.client.auction.data.canvas.DrawGraphCanvas;
import wowraidmanager.client.service.auction.AuctionListService;
import wowraidmanager.client.service.auction.AuctionListServiceAsync;
import wowraidmanager.client.service.auction.CheckItemListService;
import wowraidmanager.client.service.auction.CheckItemListServiceAsync;
import wowraidmanager.client.service.auction.RealmListService;
import wowraidmanager.client.service.auction.RealmListServiceAsync;
import wowraidmanager.shared.model.auction.AuctionList;
import wowraidmanager.shared.model.auction.CheckItemList;
import wowraidmanager.shared.model.auction.RealmList;
import wowraidmanager.shared.model.auction.canvas.AuctionCalculateData;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;

public class DataList extends BaseComposite{

    private static DataListUiBinder uiBinder = GWT.create(DataListUiBinder.class);

    static int COLUMN_CHECKITEM_ITEMNAME = 0;
    static int COLUMN_CHECKITEM_CHECKBUTTON = 1;

    static int GRAPH_CANVAS_WIDTH = 400;
    static int GRAPH_CANVAS_HEIGHT = 300;

    static int EXAMPLE_CANVAS_WIDTH = 400;
    static int EXAMPLE_CANVAS_HEIGHT = 50;

    static String REGION_ALLIANCE = "alliance";
    static String REGION_HORDE = "horde";
    static String REGION_NEUTRAL = "neutral";

    static DateTimeFormat DATE_FORMAT = DateTimeFormat.getFormat("yyyy/MM/dd");
    static Date DATE_NOW = new Date();
    static Date DATE_YESTARDAY = new Date(System.currentTimeMillis() - (24 * 60 * 60 * 1000));
    static Date DATE_WEEK = new Date(System.currentTimeMillis() - (7 * 24 * 60 * 60 * 1000));
    static Date DATE_MONTH = new Date(System.currentTimeMillis() - (7 * 24 * 60 * 60 * 1000) - (7 * 24 * 60 * 60 * 1000) - (7 * 24 * 60 * 60 * 1000) - (7 * 24 * 60 * 60 * 1000) - (2 * 24 * 60 * 60 * 1000));

    protected CheckItemListServiceAsync checkItemListService = GWT.create(CheckItemListService.class);

    protected RealmListServiceAsync realmListService = GWT.create(RealmListService.class);

    protected AuctionListServiceAsync auctionListService = GWT.create(AuctionListService.class);

    private CalculateData calculateData = new CalculateData();

    private DrawDistributionCanvas distributionCanvas;

    private DrawGraphCanvas weekDataDrawGraph;

    private DrawGraphCanvas monthDataDrawGraph;

    interface DataListUiBinder extends UiBinder<Widget, DataList>{
    }

    ArrayList<AuctionList> auctionListList;

    ArrayList<RealmList> realmListList;

    ArrayList<CheckItemList> checkItemListList;

    ArrayList<AuctionList> allianceAuctionListList;

    ArrayList<AuctionList> hordeAuctionListList;

    ArrayList<AuctionList> neutralAuctionListList;

    String currentRealm;

    String currentItemId;

    @UiField
    HTMLPanel dataPanel;

    @UiField
    HTMLPanel loadPanel;

    @UiField
    ListBox realmListListBox;

    @UiField
    ListBox typeListBox;

    @UiField
    Label serverLabel;

    @UiField
    HTMLPanel dataPricePanel;

    @UiField
    HTMLPanel loadPricePanel;

    @UiField
    HTML itemNameHTML;

    @UiField
    ScrollPanel checkItemScroolPanel;

    @UiField
    FlexTable checkItemListFlexTable;

    @UiField
    FlexTable todayFlexTable;

    @UiField
    RadioButton distributionAllianceRadioButton;

    @UiField
    RadioButton distributionHordeRadioButton;

    @UiField
    RadioButton distributionNeutralRadioButton;

    @UiField
    HTMLPanel distributionPanel;

    @UiField
    CheckBox weekAllianceCheckBox;

    @UiField
    CheckBox weekHordeCheckBox;

    @UiField
    CheckBox weekNeutralCheckBox;

    @UiField
    FlowPanel weekLineExample;

    @UiField
    HTMLPanel weekDataPanel;

    @UiField
    CheckBox monthAllianceCheckBox;

    @UiField
    CheckBox monthHordeCheckBox;

    @UiField
    CheckBox monthNeutralCheckBox;

    @UiField
    FlowPanel monthLineExample;

    @UiField
    HTMLPanel monthDataPanel;

    public DataList(){
        initWidget(uiBinder.createAndBindUi(this));
        getRealmListData();
    }

    private void setWidget(){
        setListBox();
        setcheckItemListFlexTable(checkItemListList);
        setCanvas();
        setPanelVisible();
        setCheckBox();
        setRadioButtion();
        selectType();
    }

    private void setRadioButtion(){
        distributionAllianceRadioButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setDistributionCanvas();
            }
        });

        distributionHordeRadioButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setDistributionCanvas();

            }
        });

        distributionNeutralRadioButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setDistributionCanvas();

            }
        });
    }

    private void setCheckBox(){
        weekAllianceCheckBox.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event){
                getCheckBox(weekAllianceCheckBox, weekHordeCheckBox, weekNeutralCheckBox, weekDataDrawGraph, DATE_WEEK, DATE_NOW);
            }
        });

        weekHordeCheckBox.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event){
                getCheckBox(weekAllianceCheckBox, weekHordeCheckBox, weekNeutralCheckBox, weekDataDrawGraph, DATE_WEEK, DATE_NOW);
            }
        });

        weekNeutralCheckBox.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event){
                getCheckBox(weekAllianceCheckBox, weekHordeCheckBox, weekNeutralCheckBox, weekDataDrawGraph, DATE_WEEK, DATE_NOW);
            }
        });

        monthAllianceCheckBox.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event){
                getCheckBox(monthAllianceCheckBox, monthHordeCheckBox, monthNeutralCheckBox, monthDataDrawGraph, DATE_MONTH, DATE_NOW);
            }
        });

        monthHordeCheckBox.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event){
                getCheckBox(monthAllianceCheckBox, monthHordeCheckBox, monthNeutralCheckBox, monthDataDrawGraph, DATE_MONTH, DATE_NOW);
            }
        });

        monthNeutralCheckBox.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event){
                getCheckBox(monthAllianceCheckBox, monthHordeCheckBox, monthNeutralCheckBox, monthDataDrawGraph, DATE_MONTH, DATE_NOW);
            }
        });
    }

    protected void getCheckBox(CheckBox allianceCheckBox, CheckBox hordeCheckBox, CheckBox neutralCheckBox, DrawGraphCanvas dataDrawGraph, Date dateFrom, Date dateTo){
        setAuctionList(currentItemId);

        ArrayList<AuctionList> allianceCurrentAuctionListList = null;
        ArrayList<AuctionList> hordeCurrentAuctionListList = null;
        ArrayList<AuctionList> neutraalCurrentAuctionListList = null;

        if(allianceCheckBox.getValue() == true){
            allianceCurrentAuctionListList = allianceAuctionListList;
        }

        if(hordeCheckBox.getValue() == true){
            hordeCurrentAuctionListList =hordeAuctionListList;
        }

        if(neutralCheckBox.getValue() == true){
            neutraalCurrentAuctionListList = neutralAuctionListList;
        }

        dataDrawGraph.setAuctionData(calculateData.calcAuctionDataList(allianceCurrentAuctionListList, dateFrom, dateTo), calculateData.calcAuctionDataList(hordeCurrentAuctionListList, dateFrom, dateTo), calculateData.calcAuctionDataList(neutraalCurrentAuctionListList, dateFrom, dateTo));
    }

    private void setScrollPanel(){
        checkItemScroolPanel.setSize(String.valueOf(checkItemListFlexTable.getOffsetWidth() + 50) + "px", "500px");
    }

    private void setCanvas(){

        Canvas distributionDataCanvas = Canvas.createIfSupported();
        Canvas distributionTooltipCanvas = Canvas.createIfSupported();
        Canvas weekDataCanvas = Canvas.createIfSupported();
        Canvas weekTooltipCanvas = Canvas.createIfSupported();
        Canvas monthDataCanvas = Canvas.createIfSupported();
        Canvas monthTooltipCanvas = Canvas.createIfSupported();
        Canvas weekExampleCanvas = Canvas.createIfSupported();
        Canvas monthExampleCanvas = Canvas.createIfSupported();

        if(distributionDataCanvas == null || distributionTooltipCanvas == null || weekDataCanvas == null || monthDataCanvas == null || weekExampleCanvas == null || monthExampleCanvas == null || weekTooltipCanvas == null || monthTooltipCanvas == null){
            Label notSupportCanvas01 = new Label("ご使用のブラウザはHTML５がサポートされていないため、表示されません。");
            Label notSupportCanvas02 = new Label("ご使用のブラウザはHTML５がサポートされていないため、表示されません。");
            Label notSupportCanvas03 = new Label("ご使用のブラウザはHTML５がサポートされていないため、表示されません。");
            distributionPanel.add(notSupportCanvas01);
            weekDataPanel.add(notSupportCanvas02);
            monthDataPanel.add(notSupportCanvas03);
        }else{

            setCanvasSize(distributionDataCanvas, GRAPH_CANVAS_WIDTH, GRAPH_CANVAS_HEIGHT);
            setCanvasSize(distributionTooltipCanvas, GRAPH_CANVAS_WIDTH, GRAPH_CANVAS_HEIGHT);
            setCanvasSize(weekDataCanvas, GRAPH_CANVAS_WIDTH, GRAPH_CANVAS_HEIGHT);
            setCanvasSize(weekTooltipCanvas, GRAPH_CANVAS_WIDTH, GRAPH_CANVAS_HEIGHT);
            setCanvasSize(monthDataCanvas, GRAPH_CANVAS_WIDTH, GRAPH_CANVAS_HEIGHT);
            setCanvasSize(monthTooltipCanvas, GRAPH_CANVAS_WIDTH, GRAPH_CANVAS_HEIGHT);

            setCanvasSize(weekExampleCanvas, EXAMPLE_CANVAS_WIDTH, EXAMPLE_CANVAS_HEIGHT);
            setCanvasSize(monthExampleCanvas, EXAMPLE_CANVAS_WIDTH, EXAMPLE_CANVAS_HEIGHT);

            distributionCanvas = new DrawDistributionCanvas(distributionDataCanvas, distributionTooltipCanvas);
            weekDataDrawGraph = new DrawGraphCanvas(weekDataCanvas, weekTooltipCanvas);
            monthDataDrawGraph = new DrawGraphCanvas(monthDataCanvas, monthTooltipCanvas);
            new DrawExampleCanvas(weekExampleCanvas);
            new DrawExampleCanvas(monthExampleCanvas);

            distributionPanel.setStyleName("relativePanel");
            distributionTooltipCanvas.setStyleName("frontCanvas");
            distributionDataCanvas.setStyleName("backCanvasl");

            weekDataPanel.setStyleName("relativePanel");
            weekTooltipCanvas.setStyleName("frontCanvas");
            weekDataCanvas.setStyleName("backCanvasl");

            monthDataPanel.setStyleName("relativePanel");
            monthTooltipCanvas.setStyleName("frontCanvas");
            monthDataCanvas.setStyleName("backCanvasl");

            distributionPanel.add(distributionTooltipCanvas);
            distributionPanel.add(distributionDataCanvas);
            weekLineExample.add(weekExampleCanvas);
            weekDataPanel.add(weekTooltipCanvas);
            weekDataPanel.add(weekDataCanvas);
            monthLineExample.add(monthExampleCanvas);
            monthDataPanel.add(monthTooltipCanvas);
            monthDataPanel.add(monthDataCanvas);
        }
    }

    private void setCanvasSize(Canvas canvas, int width, int height){
        canvas.setWidth(width + "px");
        canvas.setHeight(height + "px");
        canvas.setCoordinateSpaceWidth(width);
        canvas.setCoordinateSpaceHeight(height);

    }

    private void setPanelVisible(){
        dataPanel.setVisible(true);
        loadPanel.setVisible(false);
    }

    private void setcheckItemListFlexTable(ArrayList<CheckItemList> selectCheckItemListList){

        int row = 0;

        checkItemListFlexTable.removeAllRows();
        checkItemListFlexTable.setText(row, COLUMN_CHECKITEM_ITEMNAME, "ItemName");
        checkItemListFlexTable.setText(row, COLUMN_CHECKITEM_CHECKBUTTON, "PriceCheck");

        row++;
        for(CheckItemList checkItemList:selectCheckItemListList){
            String html = "<a href=\"http://www.wowhead.com/item=" + checkItemList.getItemId() + "\" target=\"_blank\" class=\"q" + checkItemList.getColorId() + "\">[" + checkItemList.getItemName() + "]</a>";
            checkItemListFlexTable.setHTML(row, COLUMN_CHECKITEM_ITEMNAME, html);
            checkItemListFlexTable.getCellFormatter().addStyleName(row, COLUMN_CHECKITEM_ITEMNAME, "itemlink");

            Button checkPriceButton = new Button("PriceCheck");
            setPriceButton(checkPriceButton, checkItemList);
            checkItemListFlexTable.setWidget(row, COLUMN_CHECKITEM_CHECKBUTTON, checkPriceButton);

            row++;
        }
    }

    private void setPriceButton(Button checkPriceButton, final CheckItemList checkItemList){
        checkPriceButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setPriceVisible(false);
                setPriceCheck(checkItemList);
            }
        });
    }

    protected void setPriceVisible(boolean isVisible){
        if(isVisible){
            dataPricePanel.setVisible(true);
            loadPricePanel.setVisible(false);
        }else{
            dataPricePanel.setVisible(false);
            loadPricePanel.setVisible(true);
        }
    }

    protected void setPriceCheck(CheckItemList checkItemList){
        currentRealm = realmListListBox.getItemText(realmListListBox.getSelectedIndex());
        currentItemId = checkItemList.getItemId();
        getAuctionListData(checkItemList);
    }

    private void setSelectItemFlexTable(CheckItemList checkItemList){
        String updateTime = "";
        for(RealmList realmList:realmListList){
            if(realmList.getRealm().equals(currentRealm)){
                updateTime = DateTimeFormat.getFormat("yyyy/MM/dd HH:mm").format(realmList.getUpdateTime());
            }
        }
        serverLabel.setText(currentRealm + " UpdateTime:" + updateTime);
        itemNameHTML.setHTML("<a href=\"http://www.wowhead.com/item=" + checkItemList.getItemId() + "\" target=\"_blank\" class=\"q" + checkItemList.getColorId() + "\">[" + checkItemList.getItemName() + "]</a>");

        setAuctionList(checkItemList.getItemId());

        setTodayPriceCheckFlexTable(allianceAuctionListList, hordeAuctionListList, neutralAuctionListList);
        setDistributionCanvas();
        setWeekPriceCheckCanvas();
        setMonthPriceCheckCanvas();
        setPriceVisible(true);
    }

    private void setDistributionCanvas(){
        boolean isAlliance = distributionAllianceRadioButton.getValue();
        boolean isHorde = distributionHordeRadioButton.getValue();
        boolean isNeutral = distributionNeutralRadioButton.getValue();

        if(isAlliance){
            distributionCanvas.setAuctionData(getTodayAuctionList(allianceAuctionListList), REGION_ALLIANCE);
        }else if(isHorde){
            distributionCanvas.setAuctionData(getTodayAuctionList(hordeAuctionListList), REGION_HORDE);
        }else if(isNeutral){
            distributionCanvas.setAuctionData(getTodayAuctionList(neutralAuctionListList), REGION_NEUTRAL);
        }
    }

    private void setAuctionList(String itemId){

        allianceAuctionListList = new ArrayList<AuctionList>();
        hordeAuctionListList = new ArrayList<AuctionList>();
        neutralAuctionListList = new ArrayList<AuctionList>();

        for(AuctionList auctionList:auctionListList){
            if(auctionList.getItemId().equals(itemId) && auctionList.getRealm().equals(currentRealm)){
                String region = auctionList.getRegion();
                if(region.equals("alliance")){
                    allianceAuctionListList.add(auctionList);
                }else if(region.equals("horde")){
                    hordeAuctionListList.add(auctionList);
                }else if(region.equals("neutral")){
                    neutralAuctionListList.add(auctionList);
                }
            }
        }
    }

    private void setMonthPriceCheckCanvas(){

        if(monthDataDrawGraph != null){
            getCheckBox(monthAllianceCheckBox, monthHordeCheckBox, monthNeutralCheckBox, monthDataDrawGraph, DATE_MONTH, DATE_NOW);
        }
    }

    private void setWeekPriceCheckCanvas(){
        if(weekDataDrawGraph != null){
            getCheckBox(weekAllianceCheckBox, weekHordeCheckBox, weekNeutralCheckBox, weekDataDrawGraph, DATE_WEEK, DATE_NOW);
        }
    }

    private void setTodayPriceCheckFlexTable(ArrayList<AuctionList> allianceAuctionListList, ArrayList<AuctionList> hordeAuctionListList, ArrayList<AuctionList> neutralAuctionListList){
        todayFlexTable.removeAllRows();
        todayFlexTable.setBorderWidth(1);
        todayFlexTable.setText(0, 1, "Alliance");
        todayFlexTable.setText(0, 2, "Horde");
        todayFlexTable.setText(0, 3, "Neutral");
        todayFlexTable.setText(1, 0, "Minimum Buyout Price");
        todayFlexTable.setText(2, 0, "Average Buyout Price");
        todayFlexTable.setText(3, 0, "Maximum Buyout Price");
        todayFlexTable.setText(4, 0, "Total Quantity(Buyout)");

        setCalculatePrice(allianceAuctionListList, todayFlexTable, 1);
        setCalculatePrice(hordeAuctionListList, todayFlexTable, 2);
        setCalculatePrice(neutralAuctionListList, todayFlexTable, 3);
    }

    private ArrayList<AuctionList> getTodayAuctionList(ArrayList<AuctionList> setAuctionListList){
        ArrayList<AuctionList> todayAuctionList = new ArrayList<AuctionList>();

        for(AuctionList auctionList:setAuctionListList){
            if(DATE_FORMAT.format(auctionList.getDate()).equals(DATE_FORMAT.format(DATE_NOW))){
                todayAuctionList.add(auctionList);
            }
        }

        if(todayAuctionList.size() == 0){
            for(AuctionList auctionList:setAuctionListList){
                if(DATE_FORMAT.format(auctionList.getDate()).equals(DATE_FORMAT.format(DATE_YESTARDAY))){
                    todayAuctionList.add(auctionList);
                }
            }
        }

        return todayAuctionList;
    }

    private void setCalculatePrice(ArrayList<AuctionList> setAuctionListList, FlexTable setFlexTable, int column){
        if(setAuctionListList.isEmpty()){
            setFlexTable.setText(1, column, "-");
            setFlexTable.setText(2, column, "-");
            setFlexTable.setText(3, column, "-");
            setFlexTable.setText(4, column, "-");
        }else{

            ArrayList<AuctionList> todayAuctionList = getTodayAuctionList(setAuctionListList);

            if(todayAuctionList.size() == 0){
                setFlexTable.setText(1, column, "-");
                setFlexTable.setText(2, column, "-");
                setFlexTable.setText(3, column, "-");
                setFlexTable.setText(4, column, "-");
            }

            for(AuctionList auctionList:todayAuctionList){

                AuctionCalculateData auctionCalculateData = calculateData.calcAuctionData(auctionList);
                setFlexTable.setText(1, column, calculateData.toGold(auctionCalculateData.getMinimumBuyoutPrice()));
                setFlexTable.setText(2, column, calculateData.toGold(auctionCalculateData.getAverageBuyoutPrice()));
                setFlexTable.setText(3, column, calculateData.toGold(auctionCalculateData.getMaximumBuyoutPrice()));
                setFlexTable.setText(4, column, String.valueOf(auctionCalculateData.getBuyoutQuantiry()));
            }

        }
    }

    protected void setListBox(){
        for(RealmList realmlist:realmListList){
            realmListListBox.addItem(realmlist.getRealm());
        }

        ArrayList<String> typeList = new ArrayList<String>();

        for(CheckItemList checkItemList:checkItemListList){
            if(!typeList.contains(checkItemList.getType())){
                typeList.add(checkItemList.getType());
            }
        }

        typeListBox.addItem("All");

        for(String type:typeList){
            typeListBox.addItem(type);
        }

        typeListBox.addChangeHandler(new ChangeHandler(){

            public void onChange(ChangeEvent event){
                selectType();
            }
        });
    }

    protected void selectType(){
        String type = typeListBox.getItemText(typeListBox.getSelectedIndex());

        if(type.equals("All")){
            setcheckItemListFlexTable(checkItemListList);
        }else{
            ArrayList<CheckItemList> selectCheckItemListList = new ArrayList<CheckItemList>();
            for(CheckItemList checkItemList:checkItemListList){
                if(type.equals(checkItemList.getType())){
                    selectCheckItemListList.add(checkItemList);
                }
            }
            setcheckItemListFlexTable(selectCheckItemListList);
        }
        setScrollPanel();
    }

    private void getAuctionListData(final CheckItemList checkItemList){
        auctionListService.getAuctionList(DATE_NOW, DATE_MONTH, checkItemList.getItemId(), currentRealm, new AsyncCallback<ArrayList<AuctionList>>(){

            public void onSuccess(ArrayList<AuctionList> result){
                auctionListList = result;
                setSelectItemFlexTable(checkItemList);
            }

            public void onFailure(Throwable caught){
                clearInfoMessage();
                setErrorMessage("AuctionListの取得に失敗しました。");
            }
        });

    }

    protected void getRealmListData(){
        realmListService.getRealmList(new AsyncCallback<ArrayList<RealmList>>(){

            public void onSuccess(ArrayList<RealmList> result){
                realmListList = result;
                getCheckItemListData();
            }

            public void onFailure(Throwable caught){
                clearInfoMessage();
                setErrorMessage("RealmListの取得に失敗しました。");
            }
        });
    }

    protected void getCheckItemListData(){
        checkItemListService.getCheckItemList(new AsyncCallback<ArrayList<CheckItemList>>(){

            public void onSuccess(ArrayList<CheckItemList> result){
                checkItemListList = result;
                setWidget();
            }

            public void onFailure(Throwable caught){
                clearInfoMessage();
                setErrorMessage("CheckItemListの取得に失敗しました。");
            }
        });
    }

}
